﻿using HDS.Common.Helper;
using HDS.Common.WordProcessing;
using HDS.IService.Log;
using HDS.Model;
using HDS.Model.Entity.Log;
using HDS.Model.Entity.Master;
using HDS.SupplierApi.Core;
using HDS.SupplierApi.Core.Entity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;

namespace HDS.SupplierApi.Hotelbeds
{
    public class SupplierHotelApi : ISupplierHotelApi
    {
        private readonly HttpClient _HttpClient;
        private readonly ILogger _ILogger;
        private readonly IApiLogService _IApiLogService;

        private SupplierApiConfig _ApiConfig;

        public SupplierHotelApi(HttpClient httpClient, ILogger ilogger, IApiLogService iapiLogService)
        {
            _HttpClient = httpClient;
            _ILogger = ilogger;
            _IApiLogService = iapiLogService;
        }

        public void LoadApiConfig(SupplierApiConfig config)
        {
            _ApiConfig = config;
        }

        public async Task<ResultData<List<SupplierRate>>> SearchRate(string[] supplierHotelIds, DateTime checkinDate, DateTime checkoutDate, RoomGuest roomGuest, string trackId, CancellationToken cancelToken)
        {
            return await SearchRate(supplierHotelIds, checkinDate, checkoutDate, roomGuest, trackId, null, null, cancelToken);
        }

        public async Task<ResultData<List<SupplierRate>>> SearchRate(string supplierHotelId, DateTime checkinDate, DateTime checkoutDate, RoomGuest roomGuest, string trackId, CancellationToken cancelToken)
        {
            return await SearchRate(new string[] { supplierHotelId }, checkinDate, checkoutDate, roomGuest, trackId, null, null, cancelToken);
        }

        public async Task<ResultData<SupplierRate>> ConfirmRate(string supplierHotelId, DateTime checkinDate, DateTime checkoutDate, RoomGuest roomGuest, string ratePlanId, string trackId, string orderId, CancellationToken cancelToken)
        {
            var resultData = await SearchRate(new string[] { supplierHotelId }, checkinDate, checkoutDate, roomGuest, trackId, ratePlanId, orderId, cancelToken);
            if (!resultData.Success)
                return new ResultData<SupplierRate> { Success = false, Code = resultData.Code, Message = resultData.Message, Data = null };

            var rate = resultData.Data.Where(e => e.RatePlanId.Equals(ratePlanId)).FirstOrDefault();
            if(rate == null)
                return new ResultData<SupplierRate> { Success = false, Code = ErrorCode.ConfirmFailure, Message = "Confirm failure", Data = null };

            if (!rate.Extras["rateType"].Equals("RECHECK"))
                return new ResultData<SupplierRate> { Success = true, Data = rate };

            return await CheckRate(rate, checkinDate, checkoutDate, roomGuest, ratePlanId, trackId, orderId, cancelToken);
        }

        public async Task<ResultData<SupplierOrderInfo>> Reservation(SupplierRate supplierRate, DateTime checkinDate, DateTime checkoutDate, RoomGuest roomGuest, string orderId, string guestRequest, CancellationToken cancelToken)
        {
            return new ResultData<SupplierOrderInfo> { 
                Success = true,
                Data = new SupplierOrderInfo
                {
                    OrderId = orderId,
                    HotelConfirmNo = "",
                    SettlementPrice = new Money { Currency = supplierRate.NetPrice.Currency, Amount = supplierRate.NetPrice.Amount },
                    Supplier = supplierRate.Supplier,
                    SupplierOrderId = $"XXX-{DateTime.Now.ToString("MMddHHmmssfff")}",
                    SupplierOrderStatus = OrderHotelStatus.Success,
                    SupplierRate = supplierRate
                }
            };
        }

        public async Task<ResultData<SupplierOrderInfo>> Cancel(string spplierOrderId, string orderId, Dictionary<string, string> extras, CancellationToken cancelToken)
        {
            return new ResultData<SupplierOrderInfo>
            {
                Success = true,
                Data = new SupplierOrderInfo
                {
                    OrderId = orderId,
                    HotelConfirmNo = "",
                    SettlementPrice = new Money { Currency = "", Amount = 0 },
                    Supplier = _ApiConfig.Supplier,
                    SupplierOrderId = spplierOrderId,
                    SupplierOrderStatus = OrderHotelStatus.Canceled,
                    SupplierRate = null
                }
            };
        }

        public Task<ResultData<SupplierOrderInfo>> GetOrder(string spplierOrderId, string orderId, Dictionary<string, string> extras, CancellationToken cancelToken)
        {
            throw new NotImplementedException();
        }



        private async Task<ResultData<List<SupplierRate>>> SearchRate(string[] supplierHotelIds, DateTime checkinDate, DateTime checkoutDate, RoomGuest roomGuest, string trackId, string ratePlanId, string orderId, CancellationToken cancelToken)
        {
            #region RequestXml

            var RequestXml = new StringBuilder();
            RequestXml.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            RequestXml.AppendFormat("<availabilityRQ xmlns=\"http://www.hotelbeds.com/schemas/messages\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" dailyRate=\"true\" sourceMarket=\"{0}\">", roomGuest.Nationality);
            RequestXml.AppendFormat("<stay checkIn=\"{0}\" checkOut=\"{1}\" />", checkinDate.ToString("yyyy-MM-dd"), checkoutDate.ToString("yyyy-MM-dd"));// shiftDays=\"5\"
            RequestXml.Append("<occupancies>");

            RequestXml.Append("<occupancy rooms=\"").Append(roomGuest.Count).Append("\" adults=\"").Append(roomGuest.Count).Append("\" children=\"").Append(roomGuest.Children).Append("\">");
            RequestXml.Append("<paxes>");
            for (var a = 0; a < roomGuest.Adults; a++)
            {
                RequestXml.Append("<pax type=\"AD\" age=\"30\"/>");
            }
            if (roomGuest.Children > 0)
            {
                foreach (var age in roomGuest.ChildrenAges)
                {
                    RequestXml.Append("<pax type=\"CH\" age=\"").Append(age).Append("\"/>");
                }
            }
            RequestXml.Append("</paxes>");
            RequestXml.Append("</occupancy>");

            RequestXml.Append("</occupancies>");
            RequestXml.Append("<hotels>");
            foreach (var hotelid in supplierHotelIds)
            {
                RequestXml.AppendFormat("<hotel>{0}</hotel>", hotelid);
            }
            RequestXml.Append("</hotels>");
            RequestXml.Append("<filter paymentType=\"AT_WEB\"/>");
            //RequestXml.Append("<filter maxRatesPerRoom=\"4\"/>");
            //RequestXml.Append("<filter packaging=\"FALSE\"/>");
            //RequestXml.Append("<filter hotelPackage=\"NO\"/>");
            RequestXml.Append("</availabilityRQ>");

            #endregion

            var apilog = new ApiLog
            {
                TrackId = trackId,
                RequestAction = supplierHotelIds.Length > 0 ? "searchs" : "search",
                RequestData = RequestXml.ToString(),
                RequestTime = DateTime.Now.GetUnixTimeStamp(),
                CheckinDate = checkinDate.GetUnixTimeStamp(),
                CheckoutDate = checkoutDate.GetUnixTimeStamp(),
                Supplier = _ApiConfig.Supplier,
                SupplierHotelId = supplierHotelIds[0],
                RatePlanId = ratePlanId,
                OrderId = orderId
            };

            var ResponseXml = await RequestAsync("hotels", HttpMethod.Post, RequestXml.ToString(), apilog, cancelToken);
            if (string.IsNullOrEmpty(ResponseXml))
            {
                return new ResultData<List<SupplierRate>>
                {
                    Code = ErrorCode.Timeout,
                    Success = false,
                    Message = "请求超时/错误",
                    Data = null
                };
            }

            var xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.LoadXml(ResponseXml);
            }
            catch (Exception ex)
            {
                return new ResultData<List<SupplierRate>>
                {
                    Code = ErrorCode.SystemError,
                    Success = false,
                    Message = ex.Message,
                    Data = null
                };
            }
            XmlElement root = xmlDoc.DocumentElement;
            string nameSpace = root.NamespaceURI;
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("N", nameSpace);
            var firstNode = xmlDoc.SelectSingleNode("/N:availabilityRS", nsmgr);

            var errorNode = firstNode.SelectSingleNode("N:error", nsmgr);
            if (errorNode != null)
            {
                return new ResultData<List<SupplierRate>>
                {
                    Code = ErrorCode.SystemError,
                    Success = false,
                    Message = string.Format("{0}|{1}", errorNode.SelectSingleNodeValue("N:code", nsmgr), errorNode.SelectSingleNodeValue("N:message", nsmgr)),
                    Data = null
                };
            }

            var rateList = new List<SupplierRate>();
            var hotelNodes = firstNode.SelectNodes("N:hotels/N:hotel", nsmgr);
            if (hotelNodes != null && hotelNodes.Count > 0)
            {
                foreach (XmlNode hotelNode in hotelNodes)
                {
                    var hotelCode = hotelNode.GetAttributesValue("code");
                    var currency = hotelNode.GetAttributesValue("currency");

                    var roomNodes = hotelNode.SelectNodes("N:rooms/N:room", nsmgr);
                    foreach (XmlNode roomNode in roomNodes)
                    {
                        var roomCode = roomNode.GetAttributesValue("code");
                        var roomName = roomNode.GetAttributesValue("name");
                        roomName = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(roomName.ToLower());

                        var rateNodes = roomNode.SelectNodes("N:rates/N:rate", nsmgr);
                        foreach (XmlNode rateNode in rateNodes)
                        {
                            if (!rateNode.Attributes["paymentType"].Value.Equals("AT_WEB"))
                                continue;

                            var rate = new SupplierRate();
                            rate.Supplier = _ApiConfig.Supplier;
                            rate.SupplierAbbr = _ApiConfig.SupplierAbbr;
                            rate.HotelId = hotelCode;

                            rate.RoomId = RoomNameEngHelper.GetSupplierRoomId(roomName);
                            rate.RoomName = roomName;
                            rate.ThirdPartyId = roomCode;

                            //房间数量
                            rate.Allotment = rateNode.GetAttributesValue("allotment").ToInt();
                            rate.MaxOccupancy = rateNode.GetAttributesValue("adults").ToInt();

                            //餐标
                            rate.MealCode = rateNode.GetAttributesValue("boardCode");
                            rate.MealDesc = rateNode.GetAttributesValue("boardName");
                            rate.MealType = GetMealType(rateNode.Attributes["boardCode"].Value, roomGuest.Adults);
                            if (rate.MealType != MealType.RoomOnly)
                                rate.MealCount = roomGuest.Adults * roomGuest.Count;
                            else
                                rate.MealCount = 0;

                            //价格
                            rate.NetPrice = new Money
                            {
                                Currency = currency,
                                Amount = rateNode.GetAttributesValue("net").ToDecimal()
                            };
                            if (rateNode.GetAttributesValue("hotelMandatory").Equals("true", StringComparison.CurrentCultureIgnoreCase))
                            {
                                rate.SellingPrice = new Money
                                {
                                    Currency = currency,
                                    Amount = rateNode.GetAttributesValue("sellingRate").ToDecimal()
                                };
                            }

                            //每日价格
                            var dailyRateNodes = rateNode.SelectNodes("N:dailyRates/N:dailyRate", nsmgr);
                            if (dailyRateNodes != null && dailyRateNodes.Count > 0)
                            {
                                rate.DailyPrices = new List<DailyPrice>();
                                var i = 0;
                                foreach (XmlNode dailyRate in dailyRateNodes)
                                {
                                    rate.DailyPrices.Add(new DailyPrice
                                    {
                                        Date = checkinDate.AddDays(i),
                                        Price = dailyRate.GetAttributesValue("dailyNet").ToDecimal(),
                                        SellingPrice = dailyRate.GetAttributesValue("dailySellingRate").ToDecimal(),
                                    });
                                    i++;
                                }
                            }

                            //取消政策
                            rate.FreeCancellationTimeLimit = GlobalVariable.NON_REFUNDABLE_HOURS;
                            var cpNodes = rateNode.SelectNodes("N:cancellationPolicies/N:cancellationPolicy", nsmgr);
                            if (cpNodes != null && cpNodes.Count > 0)
                            {
                                DateTime CancelDate = DateTime.Now.AddYears(10);
                                foreach (XmlNode cp in cpNodes)
                                {
                                    var _cd = DateTime.Parse(cp.Attributes["from"].Value);
                                    if (CancelDate > _cd)
                                        CancelDate = _cd;
                                }
                                rate.FreeCancellationTimeLimit = DateTimeHelper.GetFreeCancellationHours(checkinDate, CancelDate);
                            }

                            //其它参数
                            rate.Extras.Add("rateKey", rateNode.Attributes["rateKey"].Value);
                            rate.Extras.Add("rateType", rateNode.Attributes["rateType"].Value);

                            rate.Remarks = rateNode.GetAttributesValue("rateComments");

                            rateList.Add(rate);
                        }
                    }
                }
            }

            return new ResultData<List<SupplierRate>> { Success = true, Data = rateList };
        }

        private async Task<ResultData<SupplierRate>> CheckRate(SupplierRate rate, DateTime checkinDate, DateTime checkoutDate, RoomGuest roomGuest, string ratePlanId, string trackId, string orderId, CancellationToken cancelToken)
        {
            #region RequestXml

            var RequestXml = new StringBuilder();
            RequestXml.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            RequestXml.Append("<checkRateRQ xmlns=\"http://www.hotelbeds.com/schemas/messages\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" language=\"ENG\" upselling=\"False\">");
            RequestXml.Append("<rooms>");
            RequestXml.AppendFormat("<room rateKey=\"{0}\"/>", rate.Extras["rateKey"]);
            RequestXml.Append("</rooms>");
            RequestXml.Append("</checkRateRQ>");

            #endregion

            var apilog = new ApiLog
            {
                TrackId = trackId,
                RequestAction = "checkrates",
                RequestData = RequestXml.ToString(),
                RequestTime = DateTime.Now.GetUnixTimeStamp(),
                CheckinDate = checkinDate.GetUnixTimeStamp(),
                CheckoutDate = checkoutDate.GetUnixTimeStamp(),
                Supplier = _ApiConfig.Supplier,
                SupplierHotelId = rate.HotelId,
                RatePlanId = ratePlanId,
                OrderId = orderId
            };

            var ResponseXml = await RequestAsync("checkrates", HttpMethod.Post, RequestXml.ToString(), apilog, cancelToken);
            if (string.IsNullOrEmpty(ResponseXml))
            {
                return new ResultData<SupplierRate>
                {
                    Code = ErrorCode.Timeout,
                    Success = false,
                    Message = "请求超时/错误",
                    Data = null
                };
            }

            var xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.LoadXml(ResponseXml);
            }
            catch (Exception ex)
            {
                return new ResultData<SupplierRate>
                {
                    Code = ErrorCode.SystemError,
                    Success = false,
                    Message = ex.Message,
                    Data = null
                };
            }

            XmlElement root = xmlDoc.DocumentElement;
            string nameSpace = root.NamespaceURI;
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("N", nameSpace);
            var firstNode = xmlDoc.SelectSingleNode("/N:checkRateRS", nsmgr);

            var errorNode = firstNode.SelectSingleNode("N:error", nsmgr);
            if (errorNode != null)
            {
                var errorCode = errorNode.SelectSingleNodeValue("N:code", nsmgr);

                return new ResultData<SupplierRate>
                {
                    Code = errorCode.Equals("PRODUCT_ERROR") ? ErrorCode.ConfirmFailure : ErrorCode.SystemError,
                    Success = false,
                    Message = string.Format("{0}|{1}", errorCode, errorNode.SelectSingleNodeValue("N:message", nsmgr)),
                    Data = null
                };
            }

            var rateList = new List<SupplierRate>();
            var hotelNodes = firstNode.SelectNodes("N:hotel", nsmgr);
            if (hotelNodes != null && hotelNodes.Count > 0)
            {
                foreach (XmlNode hotelNode in hotelNodes)
                {
                    var hotelCode = hotelNode.GetAttributesValue("code");
                    var currency = hotelNode.GetAttributesValue("currency");

                    var roomNodes = hotelNode.SelectNodes("N:rooms/N:room", nsmgr);
                    foreach (XmlNode roomNode in roomNodes)
                    {
                        var roomCode = roomNode.GetAttributesValue("code");

                        var rateNodes = roomNode.SelectNodes("N:rates/N:rate", nsmgr);
                        foreach (XmlNode rateNode in rateNodes)
                        {
                            if (!rateNode.Attributes["paymentType"].Value.Equals("AT_WEB"))
                                continue;

                            var _rate = new SupplierRate();
                            _rate.Supplier = _ApiConfig.Supplier;
                            _rate.SupplierAbbr = _ApiConfig.SupplierAbbr;
                            _rate.HotelId = hotelCode;

                            _rate.RoomId = rate.RoomId;
                            _rate.RoomName = rate.RoomName;
                            _rate.ThirdPartyId = roomCode;

                            //房间数量
                            _rate.Allotment = rate.Allotment;
                            _rate.MaxOccupancy = rateNode.GetAttributesValue("adults").ToInt();

                            //餐标
                            _rate.MealCode = rateNode.GetAttributesValue("boardCode");
                            _rate.MealDesc = rateNode.GetAttributesValue("boardName");
                            _rate.MealType = GetMealType(rateNode.Attributes["boardCode"].Value, roomGuest.Adults);
                            if (_rate.MealType != MealType.RoomOnly)
                                _rate.MealCount = roomGuest.Adults * roomGuest.Count;
                            else
                                _rate.MealCount = 0;

                            //价格
                            _rate.NetPrice = new Money
                            {
                                Currency = currency,
                                Amount = rateNode.GetAttributesValue("net").ToDecimal()
                            };
                            if (rateNode.GetAttributesValue("hotelMandatory").Equals("true", StringComparison.CurrentCultureIgnoreCase))
                            {
                                _rate.SellingPrice = new Money
                                {
                                    Currency = currency,
                                    Amount = rateNode.GetAttributesValue("sellingRate").ToDecimal()
                                };
                            }

                            //每日价格
                            _rate.DailyPrices = rate.DailyPrices;

                            //取消政策
                            _rate.FreeCancellationTimeLimit = GlobalVariable.NON_REFUNDABLE_HOURS;
                            var cpNodes = rateNode.SelectNodes("N:cancellationPolicies/N:cancellationPolicy", nsmgr);
                            if (cpNodes != null && cpNodes.Count > 0)
                            {
                                DateTime CancelDate = DateTime.Now.AddYears(10);
                                foreach (XmlNode cp in cpNodes)
                                {
                                    var _cd = DateTime.Parse(cp.Attributes["from"].Value);
                                    if (CancelDate > _cd)
                                        CancelDate = _cd;
                                }
                                _rate.FreeCancellationTimeLimit = DateTimeHelper.GetFreeCancellationHours(checkinDate, CancelDate);
                            }
                            if (_rate.FreeCancellationTimeLimit > rate.FreeCancellationTimeLimit)
                                continue;
                            else
                                _rate.FreeCancellationTimeLimit = rate.FreeCancellationTimeLimit;

                            //其它参数
                            _rate.Extras.Add("rateKey", rateNode.Attributes["rateKey"].Value);
                            _rate.Extras.Add("rateType", rateNode.Attributes["rateType"].Value);

                            _rate.Remarks = rateNode.GetAttributesValue("rateComments");

                            rateList.Add(_rate);
                        }
                    }
                }
            }

            if (rateList.IsEmpty())
            {
                return new ResultData<SupplierRate> { Success = false, Code = ErrorCode.ConfirmFailure, Message = "CheckRates Not Avail", Data = null };
            }

            var _avail = rateList.Where(r => r.RatePlanId.Equals(ratePlanId)).OrderBy(r => r.NetPrice).FirstOrDefault();
            if (_avail == null)
            {
                return new ResultData<SupplierRate> { Success = false, Code = ErrorCode.ConfirmFailure, Message = "CheckRates Not Avail", Data = null };
            }

            return new ResultData<SupplierRate> { Success = true, Code = ErrorCode.OK, Data = _avail };
        }

        private MealType GetMealType(string BroadCode, int adultNum)
        {
            switch (BroadCode)
            {
                case "AB"://american breakfast
                case "BB"://bed and breakfast
                case "CB"://continental breakfast
                case "DB"://buffet breakfast
                case "GB"://english breakfast
                case "IB"://irish breakfast
                case "LB"://light breakfast
                case "SB"://scottish breakfast
                    return MealType.Breakfast;
                case "AI"://all inclusive
                case "AS"://all inclusive premium
                case "FB"://full board
                case "TL"://all inclusive soft
                case "PB"://full board beverages included
                    return MealType.BreakfastLunchDinner;
                case "HB"://half board
                case "MB"://half board with beverages included
                    return MealType.BreakfastDinner;
                case "B1"://breakfast for one guest
                    if (adultNum == 1)
                        return MealType.Breakfast;
                    else
                        return MealType.RoomOnly;
                case "B2"://breakfast for two guests
                    if (adultNum <= 2)
                        return MealType.Breakfast;
                    else
                        return MealType.RoomOnly;
                case "FH"://1 half board + 1 full board
                case "BH"://1 bed and breakfast + 1 half board
                    if (adultNum <= 2)
                        return MealType.Breakfast;
                    else
                        return MealType.RoomOnly;
                case "DD"://disney dining
                case "DX"://disney deluxe dining
                case "FL"://disney fb plus: + 15 restaurants
                case "FR"://disney fb premium: + 20 restaurants
                case "FS"://disney fb standard: + 5 restaurants
                case "HL"://disney hb plus: + 15 restaurants
                case "HR"://disney hb premium: + 20 restaurants
                case "HS"://disney hb standard: + 5 restaurants
                case "QB"://disney quick service breakfast
                case "QM"://disney quick service meal
                case "QS"://disney quick service
                case "SC"://self catering
                case "RO"://room only
                    return MealType.RoomOnly;
            }

            return MealType.RoomOnly;
        }

        #region Http Request

        private async Task<string> RequestAsync(string type, HttpMethod reqMethod, string RequestXmlData, ApiLog apilog, CancellationToken cancelToken)
        {
            apilog.RequestUrl = type;
            apilog.RequestData = RequestXmlData;

            var ApiUrl = _ApiConfig.ApiUrl + type;

            if (reqMethod.Equals(HttpMethod.Post) && type.Equals("bookings"))
            {
                ApiUrl = ApiUrl.Replace("1.0/", "1.2/");
            }

            string signature;
            using (var sha = SHA256.Create())
            {
                long ts = (long)(DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds / 1000;
                var computedHash = sha.ComputeHash(Encoding.UTF8.GetBytes(_ApiConfig.ApiId + _ApiConfig.ApiPwd + ts));
                signature = BitConverter.ToString(computedHash).Replace("-", "");
            }

            string ResponseXml = string.Empty;

            try
            {
                using (var request = new HttpRequestMessage(reqMethod, ApiUrl))
                {
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
                    request.Headers.Add("Api-Key", _ApiConfig.ApiId);
                    request.Headers.Add("X-Signature", signature);

                    request.Method = reqMethod;
                    if (reqMethod == HttpMethod.Post)
                    {
                        request.Content = new StringContent(RequestXmlData, Encoding.UTF8, "application/xml");
                    }
                    var response = await _HttpClient.SendAsync(request, cancelToken);

                    ResponseXml = await response.Content.ReadAsStringAsync();

                    apilog.ResponseData = ResponseXml;
                    apilog.RequestStatus = response.IsSuccessStatusCode ? ErrorCode.OK : ErrorCode.ApiError;

                    if (response.IsSuccessStatusCode)
                    {
                        return ResponseXml;
                    }
                    else
                    {
                        if (ResponseXml.IndexOf("<error>") > 0)
                        {
                            return ResponseXml;
                        }
                        apilog.ResponseData += System.Environment.NewLine + (int)response.StatusCode;
                        return "";
                    }
                }
            }
            catch (HttpRequestException e)
            {
                apilog.ResponseData = e.Message;
                apilog.RequestStatus = ErrorCode.SystemError;
                _ILogger.LogError(apilog.ResponseData);
            }
            catch (TaskCanceledException e)
            {
                apilog.ResponseData = e.Message;
                apilog.RequestStatus = ErrorCode.Timeout;
                _ILogger.LogError(apilog.ResponseData);
            }
            catch (Exception e)
            {
                apilog.ResponseData = e.Message;
                apilog.RequestStatus = ErrorCode.SystemError;
                _ILogger.LogError(apilog.ResponseData);
            }
            finally
            {
                apilog.ResponseTime = DateTime.Now.GetUnixTimeStamp();
                await _IApiLogService.Add(apilog, DateTime.Now);
            }

            return ResponseXml;
        }

        #endregion
    }
}
